#include "sys.h"

/**
 * HSI是高速内部时钟，RC振荡器，频率为8MHz
 * HSE是高速外部时钟，频率范围为4MHz~16MHz。
 * LSI是低速内部时钟，RC振荡器，频率为40kHz。
 * LSE是低速外部时钟，接频率为32.768kHz的石英晶体。
 * PLL为锁相环倍频输出，其时钟输入源可选择为HSI/2、HSE或者HSE/2;输出频率最大不得超过72MHz。
 */
void RCC_Configuration(void)
{
    ErrorStatus HSEStartUpStatus;
    RCC_DeInit();                               // 复位RCC成缺省值
    RCC_HSEConfig(RCC_HSE_ON);                  // 开启HSE的时钟作为PLL的时钟源
    HSEStartUpStatus = RCC_WaitForHSEStartUp(); // 获取HSE时钟状态
    if (HSEStartUpStatus == SUCCESS)            // 如果HSE启动成功
    {
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  // PLL源(外部HSE直接输入)和倍频(9)(SYSCLK=72MHz)
        RCC_HCLKConfig(RCC_SYSCLK_Div1);                      // AHB总线时钟(HCLK)=SYSCLK(72MHz)
        RCC_PCLK1Config(RCC_HCLK_Div2);                       // 低速APB1(PCLK1)=(HCLK/2)=(72MHz)/2
        RCC_PCLK2Config(RCC_HCLK_Div1);                       // 高速APB2(PCLK2)=(HCLK)=(72MHz)
        RCC_ADCCLKConfig(RCC_PCLK2_Div2);                     // ADCCLK=(PCLK2)/2
        FLASH_SetLatency(FLASH_Latency_2);                    //
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); // 开启FLASH的预取功能
        RCC_PLLCmd(ENABLE);                                   // 打开PLL
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
            ;                                      // 等待PLL稳定
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // 系统时钟SYSCLK源(PLL)
        while (RCC_GetSYSCLKSource() != 0x08)
            ; // 检查是否将PLL作为系统时钟
    }
    // 可以在此统一开启外设时钟 ....
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); // CRC
}

/**
 * @attention 在工程中执行一次即可
 */
void NVIC_Configuration(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
}
/**
 * @brief ChipID[96bit];读Flash[系统存储器]
 * @attention stm32的芯片地址为：0x1FFFF7E8~0x1FFFF7F3;
 * @attention  u32 id[3] 数组接收;
 */
void GetChipID(uint32_t *pArray)
{
    pArray[0] = *((__IO uint32_t *)0x1FFFF7E8); //
    pArray[1] = *((__IO uint32_t *)0x1FFFF7EC); //
    pArray[2] = *((__IO uint32_t *)0x1FFFF7F0); //
}

/**
 * @brief 将数据和CRC结果发给对应设备;对应设备也进行CRC计算,对比CRC结果
 * @attention 8bit独立Data(ID) register[存放临时数据,CRC复位时数据不会消失]  CRC_SetIDRegister(),CRC_GetIDRegister()
 */
uint32_t GetCRCValue(uint32_t *pBuffer, uint32_t BufferLength)
{
    uint32_t value = 0;
    CRC_ResetDR();                                   // CRC复位
    value = CRC_CalcBlockCRC(pBuffer, BufferLength); // 计算
    return value;
}

// __asm int readsp(void)
// {
//     MOV R0, sp
//                 bx lr
// }
